"""
人物业务逻辑层
"""
from typing import List, Optional, Dict, Any
from sqlalchemy.orm import Session

from app.models.character import Character, RoleType, Gender
from app.repositories.character_repo import CharacterRepository
from app.core.exceptions import NotFoundException, BadRequestException, ConflictException

class CharacterService:
    """人物业务逻辑类"""
    
    def __init__(self, db: Session):
        self.db = db
        self.character_repo = CharacterRepository(db)
    
    def get_character(self, character_id: int) -> Optional[Character]:
        """获取人物详情"""
        character = self.character_repo.get_by_id(character_id)
        if not character:
            raise NotFoundException(f"Character with id {character_id} not found")
        return character
    
    def get_character_by_name(self, name: str) -> Optional[Character]:
        """根据姓名获取人物"""
        return self.character_repo.get_by_name(name)
    
    def get_all_characters(self, skip: int = 0, limit: int = 100) -> List[Character]:
        """获取所有人物"""
        return self.character_repo.get_all(skip=skip, limit=limit)
    
    def create_character(self, character_data: Dict[str, Any]) -> Character:
        """创建人物"""
        # 验证必填字段
        if not character_data.get('name'):
            raise BadRequestException("Name is required")
        
        if not character_data.get('role_type'):
            raise BadRequestException("Role type is required")
        
        # 检查姓名是否已存在
        existing_character = self.character_repo.get_by_name(character_data['name'])
        if existing_character:
            raise ConflictException(f"Character with name '{character_data['name']}' already exists")
        
        # 验证角色类型
        try:
            RoleType(character_data['role_type'])
        except ValueError:
            raise BadRequestException(f"Invalid role type: {character_data['role_type']}")
        
        # 如果有性别，验证性别
        if character_data.get('gender'):
            try:
                Gender(character_data['gender'])
            except ValueError:
                raise BadRequestException(f"Invalid gender: {character_data['gender']}")
        
        return self.character_repo.create(character_data)
    
    def update_character(self, character_id: int, character_data: Dict[str, Any]) -> Optional[Character]:
        """更新人物"""
        character = self.character_repo.get_by_id(character_id)
        if not character:
            raise NotFoundException(f"Character with id {character_id} not found")
        
        # 如果更新姓名，检查是否与其他人重名
        if 'name' in character_data and character_data['name'] != character.name:
            existing_character = self.character_repo.get_by_name(character_data['name'])
            if existing_character and existing_character.id != character_id:
                raise ConflictException(f"Character with name '{character_data['name']}' already exists")
        
        # 验证角色类型
        if 'role_type' in character_data:
            try:
                RoleType(character_data['role_type'])
            except ValueError:
                raise BadRequestException(f"Invalid role type: {character_data['role_type']}")
        
        # 验证性别
        if 'gender' in character_data and character_data['gender']:
            try:
                Gender(character_data['gender'])
            except ValueError:
                raise BadRequestException(f"Invalid gender: {character_data['gender']}")
        
        return self.character_repo.update(character_id, character_data)
    
    def delete_character(self, character_id: int) -> bool:
        """删除人物"""
        character = self.character_repo.get_by_id(character_id)
        if not character:
            raise NotFoundException(f"Character with id {character_id} not found")
        
        return self.character_repo.delete(character_id)
    
    def search_characters(self, keyword: str) -> List[Character]:
        """搜索人物"""
        if not keyword or len(keyword.strip()) < 1:
            raise BadRequestException("Search keyword is required")
        
        return self.character_repo.search_characters(keyword.strip())
    
    def get_characters_by_role(self, role_type: str) -> List[Character]:
        """根据角色类型获取人物"""
        try:
            role = RoleType(role_type)
        except ValueError:
            raise BadRequestException(f"Invalid role type: {role_type}")
        
        return self.character_repo.get_by_role_type(role)
    
    def get_characters_by_department(self, department: str) -> List[Character]:
        """根据部门获取人物"""
        if not department or len(department.strip()) < 1:
            raise BadRequestException("Department is required")
        
        return self.character_repo.get_by_department(department.strip())
    
    def get_protagonist(self) -> Optional[Character]:
        """获取主角"""
        return self.character_repo.get_protagonist()
    
    def get_colleagues(self) -> List[Character]:
        """获取所有同事"""
        return self.character_repo.get_colleagues()
    
    def get_superiors(self) -> List[Character]:
        """获取所有上级"""
        return self.character_repo.get_superiors()
    
    def get_characters_by_age_range(self, min_age: int, max_age: int) -> List[Character]:
        """根据年龄范围获取人物"""
        if min_age < 0 or max_age < 0 or min_age > max_age:
            raise BadRequestException("Invalid age range")
        
        return self.character_repo.get_by_age_range(min_age, max_age)
    
    def get_characters_by_gender(self, gender: str) -> List[Character]:
        """根据性别获取人物"""
        try:
            g = Gender(gender)
        except ValueError:
            raise BadRequestException(f"Invalid gender: {gender}")
        
        return self.character_repo.get_by_gender(g)
    
    def update_character_basic_info(self, character_id: int, basic_info: Dict[str, Any]) -> Optional[Character]:
        """更新人物基本信息"""
        character = self.character_repo.get_by_id(character_id)
        if not character:
            raise NotFoundException(f"Character with id {character_id} not found")
        
        if not isinstance(basic_info, dict):
            raise BadRequestException("Basic info must be a dictionary")
        
        return self.character_repo.update_basic_info(character_id, basic_info)
    
    def add_personality_tag(self, character_id: int, tag: str) -> Optional[Character]:
        """添加性格标签"""
        character = self.character_repo.get_by_id(character_id)
        if not character:
            raise NotFoundException(f"Character with id {character_id} not found")
        
        if not tag or len(tag.strip()) < 1:
            raise BadRequestException("Tag is required")
        
        return self.character_repo.add_personality_tag(character_id, tag.strip())
    
    def remove_personality_tag(self, character_id: int, tag: str) -> Optional[Character]:
        """移除性格标签"""
        character = self.character_repo.get_by_id(character_id)
        if not character:
            raise NotFoundException(f"Character with id {character_id} not found")
        
        if not tag or len(tag.strip()) < 1:
            raise BadRequestException("Tag is required")
        
        return self.character_repo.remove_personality_tag(character_id, tag.strip())
    
    def get_character_statistics(self) -> Dict[str, Any]:
        """获取人物统计信息"""
        total_characters = self.character_repo.count()
        
        # 按角色类型统计
        role_stats = {}
        for role_type in RoleType:
            count = len(self.character_repo.get_by_role_type(role_type))
            role_stats[role_type.value] = count
        
        # 按部门统计
        department_stats = {}
        all_characters = self.character_repo.get_all(limit=1000)
        for character in all_characters:
            if character.department:
                department_stats[character.department] = department_stats.get(character.department, 0) + 1
        
        # 按性别统计
        gender_stats = {}
        for gender in Gender:
            count = len(self.character_repo.get_by_gender(gender))
            gender_stats[gender.value] = count
        
        return {
            "total_characters": total_characters,
            "role_distribution": role_stats,
            "department_distribution": department_stats,
            "gender_distribution": gender_stats
        }